import { myPeerIdAtom, peersAtom, store } from '@/atom'
import { filesAtom } from './atom'
import { notification } from 'antd'
import { DataConnection } from 'peerjs'
import { getNameFromId } from '@/utils/peer'

// 格式化时长的工具函数
const formatDuration = (milliseconds: number): string => {
  const seconds = Math.floor(milliseconds / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)

  if (hours > 0) {
    return `${hours}小时${minutes % 60}分${seconds % 60}秒`
  } else if (minutes > 0) {
    return `${minutes}分${seconds % 60}秒`
  } else {
    return `${seconds}秒`
  }
}

export function addFile(file: any) {
  store.set(filesAtom, (old) => [...old, file])
}

export function removeFile(id: any) {
  store.set(filesAtom, (old) => old.filter((f) => f.id !== id))
}

const chunkSize = 1024 * 1024 * 16 // 每个分片大小
const concurrentChannels = 32 // 并发通道数量

// 分片队列管理器
class ChunkQueue {
  private chunks: Array<{
    partIndex: number
    startOffset: number
    endOffset: number
    buffer: ArrayBuffer
  }> = []
  private completedChunks = 0
  private totalChunks = 0
  private activeChannels = 0

  constructor(buffer: ArrayBuffer, totalSize: number) {
    // 将文件分成固定大小的分片
    this.totalChunks = Math.ceil(totalSize / chunkSize)

    for (let i = 0; i < this.totalChunks; i++) {
      const startOffset = i * chunkSize
      const endOffset = Math.min(startOffset + chunkSize, totalSize)
      const chunkBuffer = buffer.slice(startOffset, endOffset)

      this.chunks.push({
        partIndex: i,
        startOffset,
        endOffset,
        buffer: chunkBuffer,
      })
    }
  }

  getNextChunk() {
    return this.chunks.shift()
  }

  markComplete() {
    this.completedChunks++
    this.activeChannels--
  }

  canStartNewChannel() {
    return this.activeChannels < concurrentChannels && this.chunks.length > 0
  }

  startChannel() {
    this.activeChannels++
  }

  isComplete() {
    return this.completedChunks === this.totalChunks
  }

  getTotalChunks() {
    return this.totalChunks
  }
}

export async function requestDownload(data: any) {
  const { conn, fileId } = data
  const files = store.get(filesAtom)
  const fileData = files.find((f) => f.id === fileId)
  const peers = store.get(peersAtom)
  const p = peers.find((p) => p.peerId === conn.peer)
  if (!p || !fileData) {
    console.log('peer or file not found', p, fileData)
    return
  }
  if (fileData.type === 'file' && fileData.fileHandle) {
    notification.success({
      message: `< ${getNameFromId(p.peerId)} >开始下载文件[ ${fileData.name} ]`,
    })
    const file = await fileData.fileHandle.getFile()
    const buffer = await file.arrayBuffer()
    const size = buffer.byteLength

    // 创建分片队列
    const chunkQueue = new ChunkQueue(buffer, size)
    const totalChunks = chunkQueue.getTotalChunks()

    conn.send({
      type: 'send-file-start',
      data: { fileId, size: file.size, totalChunks },
    })

    // 启动传输管理器
    await startTransferManager(conn, fileId, chunkQueue)
  } else if (fileData.type === 'file' && fileData.file) {
    notification.success({
      message: `< ${getNameFromId(p.peerId)} >开始下载文件[ ${fileData.name} ]`,
    })
    const { file } = fileData
    const buffer = await file.arrayBuffer()
    const size = buffer.byteLength

    // 创建分片队列
    const chunkQueue = new ChunkQueue(buffer, size)
    const totalChunks = chunkQueue.getTotalChunks()

    conn.send({
      type: 'send-file-start',
      data: { fileId, size: file.size, totalChunks },
    })

    // 启动传输管理器
    await startTransferManager(conn, fileId, chunkQueue)
  } else if (
    fileData.type === 'directory' &&
    fileData.dirHandle &&
    fileData.subFiles?.length
  ) {
    notification.success({
      message: `< ${getNameFromId(p.peerId)} >开始下载文件夹[ ${fileData.name} ]`,
    })
    for await (const subFile of fileData.subFiles) {
      const file = await subFile.fileHandle.getFile()
      const buffer = await file.arrayBuffer()
      const size = buffer.byteLength

      // 创建分片队列
      const chunkQueue = new ChunkQueue(buffer, size)
      const totalChunks = chunkQueue.getTotalChunks()

      conn.send({
        type: 'send-file-start',
        data: {
          fileId,
          downloadingId: subFile.id,
          size: file.size,
          totalChunks,
        },
      })

      // 启动传输管理器
      await startTransferManager(conn, fileId, chunkQueue, subFile.id)
    }
  }
}

// 传输管理器：管理固定数量的并发通道
async function startTransferManager(
  conn: DataConnection,
  fileId: string,
  chunkQueue: ChunkQueue,
  downloadingId?: string,
) {
  return new Promise<void>((resolve) => {
    const processChannel = async () => {
      while (chunkQueue.canStartNewChannel()) {
        chunkQueue.startChannel()

        const processChunk = async () => {
          const chunk = chunkQueue.getNextChunk()
          if (!chunk) {
            chunkQueue.markComplete()
            if (chunkQueue.isComplete()) {
              resolve()
            }
            return
          }

          // 发送分片
          await sendChunk(conn, fileId, chunk, downloadingId)
          chunkQueue.markComplete()

          // 如果还有分片要发送，继续处理
          if (!chunkQueue.isComplete() && chunkQueue.canStartNewChannel()) {
            processChunk()
          } else if (chunkQueue.isComplete()) {
            resolve()
          }
        }

        processChunk()
      }
    }

    processChannel()
  })
}

// 发送单个分片
async function sendChunk(
  conn: DataConnection,
  fileId: string,
  chunk: {
    partIndex: number
    startOffset: number
    endOffset: number
    buffer: ArrayBuffer
  },
  downloadingId?: string,
) {
  const { partIndex, startOffset, endOffset, buffer: partBuffer } = chunk
  const messageData: any = {
    fileId,
    buffer: partBuffer,
    partIndex,
    chunkOffset: startOffset,
    chunkEnd: endOffset,
  }

  if (downloadingId) {
    messageData.downloadingId = downloadingId
  }

  conn.send({
    type: 'send-file',
    data: messageData,
  })

  // 添加小延迟避免过快发送导致的问题
  await new Promise((resolve) => setTimeout(resolve, 1))
}

// export async function requestDownloadLegacy(data: any) {
//   const { conn, fileId } = data
//   const files = store.get(filesAtom)
//   const fileData = files.find((f) => f.id === fileId)
//   if (fileData.type === 'file' && fileData.file) {
//     const { file } = fileData
//     conn.send({
//       type: 'send-file-start',
//       data: { fileId, size: file.size },
//     })
//     const buffer = await file.arrayBuffer()
//     const size = buffer.byteLength
//     let start = 0
//     let end = size > chunkSize ? chunkSize : size
//     let sendBuffer = buffer.slice(start, end)
//     while (sendBuffer.byteLength > 0) {
//       conn.send({
//         type: 'send-file',
//         data: {
//           fileId,
//           buffer: sendBuffer,
//           // start,
//           end,
//           // size,
//         },
//       })
//       start = end
//       end = size > start + chunkSize ? start + chunkSize : size
//       sendBuffer = buffer.slice(start, end)
//     }
//   }
// }

export async function startReceiveFile(data: any) {
  const { fileId, size, totalChunks = 1 } = data
  const filesData = store.get(filesAtom)
  const fileData = filesData.find((f) => f.id === fileId)
  if (fileData?.type === 'file') {
    store.set(filesAtom, (o) =>
      o.map((f) => {
        if (f.id === fileId) {
          return {
            ...f,
            downloading: {
              totalSize: size,
              totalChunks,
              receivedChunks: new Map(), // 使用 Map 存储接收到的分片
              receivedSize: 0,
              startTime: Date.now(),
              speed: 0,
              percentage: 0,
              lastUpdateTime: Date.now(),
              lastReceivedSize: 0,
              duration: 0, // 总下载时长（毫秒）
              isCompleted: false, // 是否下载完成
            },
          }
        }
        return f
      }),
    )
  } else if (fileData?.type === 'directory') {
    const { downloadingId } = data

    store.set(filesAtom, (o) =>
      o.map((f) => {
        if (f.id === fileId) {
          return {
            ...f,
            downloading: true,
            subFiles: f.subFiles.map((f: any) => {
              if (f.id === downloadingId) {
                return {
                  ...f,
                  totalSize: size,
                  totalChunks,
                  receivedChunks: new Map(), // 使用 Map 存储接收到的分片
                  receivedSize: 0,
                  startTime: Date.now(),
                  speed: 0,
                  percentage: 0,
                  lastUpdateTime: Date.now(),
                  lastReceivedSize: 0,
                  duration: 0, // 总下载时长（毫秒）
                  isCompleted: false, // 是否下载完成
                }
              }
              return f
            }),
          }
        }
        return f
      }),
    )
  }
}

export async function createFileWritable(
  directoryHandle: FileSystemDirectoryHandle,
  fileName: string,
  relativePaths: string[],
) {
  let currentDirectory = directoryHandle
  for (const part of relativePaths) {
    currentDirectory = await currentDirectory.getDirectoryHandle(part, {
      create: true,
    })
  }

  const fileHandle = await currentDirectory.getFileHandle(fileName, {
    create: true,
  })

  const writable = await fileHandle.createWritable()

  return writable
}

export function downloadFile(data: any, conn: DataConnection) {
  const { fileId, buffer, partIndex = 0 } = data
  const files = store.get(filesAtom)
  const fileData = files.find((f) => f.id === fileId)

  if (fileData?.type === 'file' && fileData.writable) {
    // 处理固定分片大小的文件接收
    store.set(filesAtom, (o) =>
      o.map((f) => {
        if (f.id === fileId) {
          const downloading = f.downloading
          const receivedChunks = downloading.receivedChunks || new Map()

          // 存储接收到的分片
          receivedChunks.set(partIndex, buffer)

          // 计算总的已接收大小
          let totalReceivedSize = 0
          receivedChunks.forEach((chunk: ArrayBuffer) => {
            totalReceivedSize += chunk.byteLength
          })

          // 计算下载百分比
          const percentage = Math.floor(
            (totalReceivedSize / downloading.totalSize) * 100,
          )

          // 计算下载速度
          const currentTime = Date.now()
          const timeDiff = currentTime - downloading.lastUpdateTime
          let speed = downloading.speed

          // 每隔500ms更新一次速度计算，避免频繁计算
          if (timeDiff > 500) {
            const sizeDiff = totalReceivedSize - downloading.lastReceivedSize
            speed = timeDiff > 0 ? Math.floor((sizeDiff * 1000) / timeDiff) : 0
          }

          // 检查是否所有分片都接收完成
          const allChunksReceived =
            receivedChunks.size === downloading.totalChunks

          if (allChunksReceived) {
            // 按照 partIndex 顺序重组文件
            const finalBuffer = new Uint8Array(downloading.totalSize)
            let offset = 0

            for (let i = 0; i < downloading.totalChunks; i++) {
              const chunk = receivedChunks.get(i)
              if (chunk) {
                const chunkData = new Uint8Array(chunk)
                finalBuffer.set(chunkData, offset)
                offset += chunkData.length
              }
            }

            // 计算总下载时长
            const downloadDuration = Date.now() - downloading.startTime

            // 一次性写入合并后的数据
            f.writable.write(finalBuffer).then(() => {
              f.writable.close()
              notification.success({
                message: `文件[ ${f.name} ]下载完成，耗时: ${formatDuration(downloadDuration)}`,
              })
              const myPeerId = store.get(myPeerIdAtom)
              conn.send({
                type: 'download-complete',
                data: { fileId, peerId: myPeerId },
              })
            })

            // 更新下载状态为已完成
            return {
              ...f,
              downloading: {
                ...downloading,
                receivedChunks,
                receivedSize: totalReceivedSize,
                percentage: 100,
                speed: 0, // 下载完成后速度归零
                duration: downloadDuration,
                isCompleted: true,
                lastUpdateTime: currentTime,
                lastReceivedSize: totalReceivedSize,
              },
            }
          }

          return {
            ...f,
            downloading: {
              ...downloading,
              receivedChunks,
              receivedSize: totalReceivedSize,
              percentage,
              speed,
              lastUpdateTime:
                timeDiff > 500 ? currentTime : downloading.lastUpdateTime,
              lastReceivedSize:
                timeDiff > 500
                  ? totalReceivedSize
                  : downloading.lastReceivedSize,
            },
          }
        }
        return f
      }),
    )
  } else if (fileData?.type === 'file') {
    // 对于不支持 writable 的情况，使用相同的逻辑
    store.set(filesAtom, (o) =>
      o.map((f) => {
        if (f.id === fileId) {
          const downloading = f.downloading
          const receivedChunks = downloading.receivedChunks || new Map()

          // 存储接收到的分片
          receivedChunks.set(partIndex, buffer)

          // 计算总的已接收大小
          let totalReceivedSize = 0
          receivedChunks.forEach((chunk: ArrayBuffer) => {
            totalReceivedSize += chunk.byteLength
          })

          // 计算下载百分比
          const percentage = Math.floor(
            (totalReceivedSize / downloading.totalSize) * 100,
          )

          // 计算下载速度
          const currentTime = Date.now()
          const timeDiff = currentTime - downloading.lastUpdateTime
          let speed = downloading.speed

          if (timeDiff > 500) {
            const sizeDiff = totalReceivedSize - downloading.lastReceivedSize
            speed = timeDiff > 0 ? Math.floor((sizeDiff * 1000) / timeDiff) : 0
          }

          // 检查是否所有分片都接收完成
          const allChunksReceived =
            receivedChunks.size === downloading.totalChunks

          if (allChunksReceived) {
            // 按照 partIndex 顺序重组文件
            const finalBuffer = new Uint8Array(downloading.totalSize)
            let offset = 0

            for (let i = 0; i < downloading.totalChunks; i++) {
              const chunk = receivedChunks.get(i)
              if (chunk) {
                const chunkData = new Uint8Array(chunk)
                finalBuffer.set(chunkData, offset)
                offset += chunkData.length
              }
            }

            // 计算总下载时长
            const downloadDuration = Date.now() - downloading.startTime

            // 创建文件并下载
            const file = new Blob([finalBuffer], { type: f.contentType })
            const url = URL.createObjectURL(file)
            const a = document.createElement('a')
            a.href = url
            a.download = f.name
            a.target = '_blank'
            a.click()
            URL.revokeObjectURL(url)
            notification.success({
              message: `文件[ ${f.name} ]下载完成，耗时: ${formatDuration(downloadDuration)}`,
            })
            const myPeerId = store.get(myPeerIdAtom)
            conn.send({
              type: 'download-complete',
              data: { fileId, peerId: myPeerId },
            })

            // 更新下载状态为已完成
            return {
              ...f,
              downloading: {
                ...downloading,
                receivedChunks,
                receivedSize: totalReceivedSize,
                percentage: 100,
                speed: 0, // 下载完成后速度归零
                duration: downloadDuration,
                isCompleted: true,
                lastUpdateTime: currentTime,
                lastReceivedSize: totalReceivedSize,
              },
            }
          }

          return {
            ...f,
            downloading: {
              ...downloading,
              receivedChunks,
              receivedSize: totalReceivedSize,
              percentage,
              speed,
              lastUpdateTime:
                timeDiff > 500 ? currentTime : downloading.lastUpdateTime,
              lastReceivedSize:
                timeDiff > 500
                  ? totalReceivedSize
                  : downloading.lastReceivedSize,
            },
          }
        }
        return f
      }),
    )
  } else if (fileData?.type === 'directory') {
    const { downloadingId } = data
    const subFile = fileData.subFiles.find((f: any) => f.id === downloadingId)
    if (subFile) {
      store.set(filesAtom, (o) =>
        o.map((f) => {
          if (f.id === fileId) {
            return {
              ...f,
              subFiles: f.subFiles.map((sf: any) => {
                if (sf.id === downloadingId) {
                  const receivedChunks = sf.receivedChunks || new Map()

                  // 存储接收到的分片
                  receivedChunks.set(partIndex, buffer)

                  // 计算总的已接收大小
                  let totalReceivedSize = 0
                  receivedChunks.forEach((chunk: ArrayBuffer) => {
                    totalReceivedSize += chunk.byteLength
                  })

                  // 计算下载百分比
                  const percentage = Math.floor(
                    (totalReceivedSize / sf.totalSize) * 100,
                  )

                  // 计算下载速度
                  const currentTime = Date.now()
                  const timeDiff = currentTime - sf.lastUpdateTime
                  let speed = sf.speed

                  if (timeDiff > 500) {
                    const sizeDiff = totalReceivedSize - sf.lastReceivedSize
                    speed =
                      timeDiff > 0
                        ? Math.floor((sizeDiff * 1000) / timeDiff)
                        : 0
                  }

                  // 检查是否当前子文件的所有分片都接收完成
                  const allChunksReceived =
                    receivedChunks.size === sf.totalChunks

                  if (allChunksReceived) {
                    // 按照 partIndex 顺序重组当前子文件
                    const finalBuffer = new Uint8Array(sf.totalSize)
                    let offset = 0

                    for (let i = 0; i < sf.totalChunks; i++) {
                      const chunk = receivedChunks.get(i)
                      if (chunk) {
                        const chunkData = new Uint8Array(chunk)
                        finalBuffer.set(chunkData, offset)
                        offset += chunkData.length
                      }
                    }

                    // 计算总下载时长
                    const downloadDuration = Date.now() - sf.startTime

                    // 一次性写入合并后的数据
                    sf.writable.write(finalBuffer).then(() => {
                      sf.writable.close()
                      notification.success({
                        message: `文件[ ${sf.name} ]下载完成，耗时: ${formatDuration(downloadDuration)}`,
                      })

                      // 检查文件夹中的所有文件是否都下载完成
                      const allCompleted = f.subFiles.every(
                        (file: any) =>
                          file.id === downloadingId ||
                          (file.receivedSize &&
                            file.receivedSize === file.totalSize),
                      )

                      if (allCompleted) {
                        notification.success({
                          message: `文件夹[ ${f.name} ]下载完成`,
                        })
                        const myPeerId = store.get(myPeerIdAtom)
                        conn.send({
                          type: 'download-complete',
                          data: { fileId, peerId: myPeerId },
                        })
                      }
                    })

                    // 更新子文件下载状态为已完成
                    return {
                      ...sf,
                      receivedChunks,
                      receivedSize: totalReceivedSize,
                      percentage: 100,
                      speed: 0, // 下载完成后速度归零
                      duration: downloadDuration,
                      isCompleted: true,
                      lastUpdateTime: currentTime,
                      lastReceivedSize: totalReceivedSize,
                    }
                  }

                  return {
                    ...sf,
                    receivedChunks,
                    receivedSize: totalReceivedSize,
                    percentage,
                    speed,
                    lastUpdateTime:
                      timeDiff > 500 ? currentTime : sf.lastUpdateTime,
                    lastReceivedSize:
                      timeDiff > 500 ? totalReceivedSize : sf.lastReceivedSize,
                  }
                }
                return sf
              }),
            }
          }
          return f
        }),
      )
    }
  } else {
    conn.send({
      type: 'send-file-error',
      data: fileId,
    })
  }
}

export async function getFilesRecursively(directoryHandle: any) {
  const files = []
  for await (const entry of directoryHandle.values()) {
    if (entry.kind === 'file') {
      files.push(entry)
    } else if (entry.kind === 'directory') {
      const subFiles: any = await getFilesRecursively(entry)
      files.push(...subFiles)
    }
  }
  return files
}
